﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace DbService.Repository
{
    using Models.CAttribute;

    public static class RepositoryHelper
    {
        /// <summary>
        /// 对 T 对象 创建一个实例
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public static T CreateInstance<T>() where T : class
        {
            return (T)Activator.CreateInstance(typeof(T));
        }

        /// <summary>
        /// 计算 Expression 对象
        /// </summary>
        /// <param name="_Expression"></param>
        /// <returns></returns>
        public static object Eval(Expression _Expression)
        {
            var cast = Expression.Convert(_Expression, typeof(object));
            return Expression.Lambda<Func<object>>(cast).Compile().Invoke();
        }

        /// <summary>
        /// 获取 实体 主键 的名称 和 值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_Entity"></param>
        /// <param name="_ForeachAction"></param>
        /// <returns></returns>
        public static Tuple<string, object> GetEntityKey<T>(T _Entity, Action<PropertyInfo> _ForeachAction = null) where T : class
        {
            var _KeyName = string.Empty;
            object _KeyValue = null;

            foreach (var item in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                //忽略主键
                if (item.GetCustomAttribute<System.ComponentModel.DataAnnotations.KeyAttribute>() != null)
                {
                    _KeyName = item.Name;
                    _KeyValue = item.GetValue(_Entity);
                    continue;
                }
                _ForeachAction?.Invoke(item);
            }
            return new Tuple<string, object>(_KeyName, _KeyValue);
        }

        /// <summary>
        /// 根据实体对象 的 ID 创建 Expression<Func<T, bool>> 表达式树
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_KeyName"></param>
        /// <param name="_KeyValue"></param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> WhereById<T>(string _KeyName, object _KeyValue) where T : class
        {
            //创建 Where Lambda表达式树
            var _Type = typeof(T);
            var _Where_Parameter = Expression.Parameter(_Type, "_Where_Parameter");
            var _Property = _Type.GetProperty(_KeyName);
            if (_Property.PropertyType != typeof(Nullable<>) && _KeyValue == null)
            {
                if (_Property.PropertyType == typeof(Guid)) _KeyValue = Guid.Empty;
                if (_Property.PropertyType == typeof(int)) _KeyValue = Int32.MinValue;
            }
            var _Left = Expression.Property(_Where_Parameter, _Property);
            var _Right = Expression.Constant(_KeyValue);
            var _Where_Body = Expression.Equal(_Left, _Right);
            return Expression.Lambda<Func<T, bool>>(_Where_Body, _Where_Parameter);
        }

        /// <summary>
        /// 检查是否有 SysNumber 特性
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="_Entity"></param>
        /// <param name="_Action"></param>
        public static void CheckedSysNumberAttribute<T>(T _Entity, Action<PropertyInfo, int, char> _Action) where T : class
        {
            foreach (var item in typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance))
            {
                //如果 有编号特性标记
                var _SysNumberAttribute = item.GetCustomAttribute<SysNumberAttribute>();
                if (_SysNumberAttribute != null)
                {
                    _Action?.Invoke(item, _SysNumberAttribute.Length, _SysNumberAttribute.Str);
                }
            }
        }



    }
}
